using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;
using XNAGameEngine.Logs;

namespace XNAGameEngine.GameState
{
    /// <summary>
    /// <para>Container class that manages the storage and retrieval of GameStateTransition objects.</para>
    /// <para>Allows for easy storage and retrieval of GameStateTransition objects as well as prevents
    /// multiple GameStateTransitions from being registered under the same string value.</para>
    /// </summary>
    public sealed class GameStateTransitionRegistry
    {
        #region local fields

        /// <summary>
        /// Container to store all of the transition objects. 
        /// </summary>
        private Dictionary<string, Type> _transitionRegistry;

        private ManagerGameState _gameStateManager;
        #endregion

        #region constructors

        /// <summary>
        /// Construct the GameStateTransitionRegistry. 
        /// </summary>
        public GameStateTransitionRegistry(ManagerGameState gameStateManager)
        {
            _transitionRegistry = new Dictionary<string, Type>();
            RegisterGameStateTransition("FadeToBlack", typeof(GSTFadeToBlack));
            RegisterGameStateTransition("FadeToGray", typeof(GSTFadeToGray));
            RegisterGameStateTransition("FadeToWhite", typeof(GSTFadeToWhite));
            _gameStateManager = gameStateManager;
            ManagerLogs.Write("GameStateTransitionRegistry : Created");
        }

        #endregion

        #region local methods

        /// <summary>
        /// Registers an GameStateTransition object type with a string string value. 
        /// </summary>
        /// <param name="key">the string to register with the object type</param>
        /// <param name="value">the object type to register with the string</param>
        public void RegisterGameStateTransition(string key, Type value)
        {
            if (_transitionRegistry.ContainsKey(key))
                throw new SystemException("string passed in is already registered to a Transition");

            if (_transitionRegistry.ContainsValue(value))
                throw new SystemException("GameStateTransition passed in is already registered");

            if (!value.IsSubclassOf(typeof(GameStateTransition)))
                throw new SystemException("Cannot register this type. Type passed does not inherit GameStateTransition");

            //add it to the registry
            _transitionRegistry.Add(key, value);
        }

        /// <summary>
        /// Return a GameStateTransition based on the string value passed in.
        /// </summary>
        /// <param name="key">the string value of the GameStateTransition needed</param>
        /// <returns>the GameStateTransition registered with the value passed in</returns>
        public GameStateTransition GetGameStateTransition(string key)
        {
            if (!_transitionRegistry.ContainsKey(key))
                throw new SystemException("no GameStateTransition registered with the passed in string value");

            object[] args = new object[2];
            args[0] = _gameStateManager.Game.GraphicsDevice;
            args[1] = new SpriteBatch(_gameStateManager.Game.GraphicsDevice);

            return (GameStateTransition)_transitionRegistry[key].GetConstructors()[0].Invoke(args);
        }

        #endregion
    }
}
